#ifndef __LOG_HPP__
#define __LOG_HPP__

#pragma once

#include <iostream>
#include <ctime>
#include <unistd.h>
#include <cstdarg>
#include "LockGuard.hpp"
#include <fstream>
enum Level
{
    DEBUG = 0,
    INFO,
    WARNING,
    ERROR,
    FATAL
};
bool g_IsSave=false;
const std::string logname = "log.txt";

std::string LevelToString(int level)
{
    switch(level)
    {
        case DEBUG:
            return "Debug";
        case INFO:
            return "Info";
        case WARNING:
            return "Warning";
        case ERROR:
            return "Error";
        case FATAL:
            return "Fatal";
        default:
            return "Unknown Level";
    }
}
std::string GetTimeString()
{
    time_t curr_time = time(nullptr);
    struct tm* format_time = localtime(&curr_time);

    if(format_time == nullptr)
        return "Unknown Time";
    char time_buffer[1024];
    snprintf(time_buffer,sizeof(time_buffer),"%d-%d-%d %d:%d:%d",
            format_time->tm_year + 1900,
            format_time->tm_mon+1,
            format_time->tm_mday,
            format_time->tm_hour,
            format_time->tm_min,
            format_time->tm_sec);
    return time_buffer;
}
void SaveFile(const std::string& filename,std::string& message)
{
    std::ofstream out(filename,std::ios::app);

    if(!out.is_open())
    {
        return;
    }
    out << message;
    out.close();
}
pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
void LogMessage(std::string filename,int line,bool issave,int level,const char* format,...)
{

    std::string levelstr = LevelToString(level);
    std::string timestr = GetTimeString();
    pid_t selfid = getpid();

    //处理可变参数列表（重点）
    char buffer[1024];
    va_list arg;
    va_start(arg,format);//这一步的目的是让arg能通过format找到后面的所有参数
    vsnprintf(buffer,sizeof(buffer),format,arg);
    va_end(arg);

    std::string message = "["+timestr+"]"
                          +"["+levelstr+"]"
                          +"["+" PID: "+std::to_string(selfid)+"]"
                          +"["+filename+"]"
                          +"["+std::to_string(line)+"]"
                          +buffer+"\n";
    
    //下面就是打印，显示器也是共享资源，需要对std::cout加锁
    LockGuard tmp_lock(g_mutex);
    if(!issave)
    {
        std::cout << message;
    }
    else{
        SaveFile(logname,message);
    }

}
//C99新特性_VA_ARGS__ （宏支持可变参数）
#define LOG(level,format,...)\
do                           \
{                            \
    LogMessage(__FILE__,__LINE__,g_IsSave,level,format,##__VA_ARGS__); \
} while (0)
    

#define EnableFile()     \
    do                   \
    {                    \
        g_IsSave = true; \
    } while (0)

#define EnableScreen()   \
    do                   \
    {                    \
        g_IsSave = false;\
    }while(0)
    
#endif